﻿// Decompiled with JetBrains decompiler
// Type: Netick.LinkedAllocator
// Assembly: Netick, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 6726ECA1-C773-4CF7-8952-E81B30D93B52
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.dll
// XML documentation location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.xml

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

#nullable disable
namespace Netick;

internal class LinkedAllocator : IAllocator
{
  internal List<NetickAllocator> _registeredBuffers = new List<NetickAllocator>(512 /*0x0200*/);
  internal NetickAllocator _allocator;
  internal NetickAllocator _helperAllocator;

  public LinkedAllocator(long poolSize)
  {
    this._allocator = new NetickAllocator(poolSize);
    this._helperAllocator = new NetickAllocator(poolSize);
  }

  public void CopyTo(NetickAllocator dest) => this._allocator.CopyTo(dest);

  public void Link(NetickAllocator buffer) => this._registeredBuffers.Add(buffer);

  public void UnlinkBuffer(NetickAllocator buffer) => this._registeredBuffers.Remove(buffer);

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public unsafe void* Allocate(ulong sizeBytes, out int poolIndex, out long offset, bool clearMem)
  {
    void* voidPtr = this._helperAllocator.Malloc(sizeBytes, out poolIndex, out offset);
    if ((IntPtr) voidPtr == IntPtr.Zero)
    {
      this._helperAllocator.AddNewPool(true);
      this._allocator.AddNewPool(false);
      for (int index = 0; index < this._registeredBuffers.Count; ++index)
        this._registeredBuffers[index].AddNewPool(false);
      voidPtr = this._helperAllocator.Malloc(sizeBytes, out poolIndex, out offset);
    }
    if ((IntPtr) voidPtr == IntPtr.Zero)
      NetickLogger.LogError((object) $"Netick: allocation failed: allocator was unable to find a block of {sizeBytes} bytes or bigger.\nPlease increase the memory allocator block size.");
    byte* ptr = (byte*) ((IntPtr) this._allocator.Blocks[poolIndex].Ptr + (IntPtr) offset);
    if (clearMem)
      MemoryAllocation.Clear((void*) ptr, (long) sizeBytes);
    return (void*) ptr;
  }

  public unsafe void Deallocate(void* ptr) => NetickLogger.LogError((object) "Don't Call This.");

  public unsafe void Free(long offset, int poolIndex)
  {
    this._helperAllocator.Free((void*) ((IntPtr) this._helperAllocator.Blocks[poolIndex].Ptr + (IntPtr) offset));
  }
}
